
function [U_out, params] = ActionFun(params, U_in)
% U_out: 接收端处的复振幅光场
% U_in：初始复振幅光场

layers = params.layers;
N = params.N;
D = params.D;
lambda = params.lambda;
L = params.L;
Cn2 = params.Cn2;
sp = params.sp;

% 频率域坐标系生成
df = 1/D; % 频率域间隔
f = [-N/2:N/2-1]*df;
[fx, fy] = meshgrid(f,f);

% 光束的二维光场函数（初始光束）
% U_in = GaussianBeam(params, D/50); % 得额外输入一个高斯光束的宽度

% 生成多层相位屏的分段边界和相位屏位置参数
[H_m, h_m] = mutilayer_generate(L,layers,Cn2,200);

% 计算每一段分层的湍流路径上的Fried常数r0m，和湍流路径上总的r0
r0m = zeros(1,layers);
for i = 1:layers
    r0m(i) = r0_generate(Cn2,lambda,H_m(i),H_m(i+1),sp,L);
end
r0 = r0m_merge(r0m);

% 生成大气湍流相位屏（此处用的是FFT-based method）
ph = zeros(N,N,layers);
for i = 1:layers
    ph(:,:,i) = MainFun_FFT_Based_method(params,r0m(i));
end

% 传播方向与路径z的定义相反，所以在参数索引时需要逆着来
% 模拟经过多层相位屏和真空衍射传播后的光场
% 真空传输衍射的次数为相位屏层数+1
U_out = U_in; % 创建接受端处的光场矩阵
count = 0; % 传输经过相位屏的次数
for i = 1:layers+1
    % 计算真空衍射的传播距离delta_z
    % 两次特殊：第一次(光源到相位屏)和最后一次传输（相位屏到接收端）
    if i == 1
        delta_z = H_m(end) - h_m(end);
    elseif i == (layers+1)
        count = count + 1;
        delta_z = h_m(1) - H_m(1);
    else
        count = count + 1;
        delta_z = h_m(end+1-count) - h_m(end-count);
    end
    % 复振幅光场加上相位屏相位
    if i == 1
        % 从光源出发的第一次传播时没有经过相位屏引入的额外相位差
    else
        ph_tmp = ph(:,:,end+1-count);
        U_out = U_out.*exp(1i*ph_tmp);
    end
    % 第i次在真空中经过菲涅尔衍射一段距离后的光场
    U_out = Fresnel_Diffraction(U_out, delta_z, lambda, fx, fy, D);
end

% 往params里添加新字段，方便过程参数的输出
params.H_m = H_m;
params.h_m = h_m;
params.r0m = r0m;
params.r0 = r0;


% end of the function
end